package org.twdata.pipeline;

import java.util.*;
import org.twdata.pipeline.stage.AbstractTransformer;
import org.xml.sax.SAXException;

/**
 *  Default mutable pipeline which uses StageBuilders to retrieve pipeline
 *  stages, then links them together and starts the generator. StageManager is
 *  used to manage stage lifecycles.
 */
public class DefaultPipeline extends MutablePipeline {

    /**
     *  Sets the stageManager to manage stage lifecycles
     *
     *@param  mgr  The new stageManager value
     */
    public void setStageManager(StageManager mgr) {
        this.stageManager = mgr;
    }


    /**
     *  Executes the pipeline.  The stage builders are used to retrieve a 
     * configured instance of each stage.  The stages are then connected and 
     * the generator is started.  Afterwards, the stage instances are recycled.
     *
     *@param  ctx                    The context information
     *@exception  PipelineException  If something goes wrong
     */
    public void execute(PipelineContext ctx)
        throws PipelineException {
        Generator gen = (Generator) generatorBuilder.build(ctx);
        Serializer ser = (Serializer) serializerBuilder.build(ctx);

        connect(gen, ser, ctx);
        gen.generate();

        stageManager.release(gen);
        stageManager.release(ser);
    }


    /**
     *  Connects existing an existing producer and consumer to this pipeline
     *
     * @param producer The xml source
     * @param consumer The xml result
     * @param ctx The pipeline context
     */
    public void connect(XMLProducer producer, XMLConsumer consumer, PipelineContext ctx) 
        throws PipelineException {

        final ArrayList validTransformers = new ArrayList();
        int x = 0;
        StageBuilder builder;
        for (Iterator i = transformerBuilders.iterator(); i.hasNext(); x++) {
            builder = (StageBuilder) i.next();
            //if (builder.isApplicable(ctx)) {
            validTransformers.add(builder.build(ctx));
            //}
        }
        validTransformers.add(new AbstractTransformer() {
            public void endDocument() throws SAXException {
                super.endDocument();
                try {
                    for (Iterator i = validTransformers.iterator(); i.hasNext(); ) {
                        stageManager.release((Stage)i.next());
                    }
                } catch (PipelineException ex) {
                    throw new SAXException(ex);
                }    
            }
        });

        Transformer[] trans = new Transformer[validTransformers.size()];
        trans = (Transformer[]) validTransformers.toArray(trans);

        producer.setConsumer(trans[0]);
        for (x = 0; x < trans.length - 1; x++) {
            trans[x].setConsumer(trans[x + 1]);
        }
        trans[trans.length - 1].setConsumer(consumer);
    }
}

